using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Threading;
using System.Text.RegularExpressions;

namespace DbService
{
   /// <summary>
   /// TransactieQueue is a subclass of the System.Collections.Generic.List class and
   /// can be used to queue Transactie objects for caching of transaction data. The
   /// TransactieQueue class is a Singleton to ensure that only one instance of the class
   /// is created and available. A List is used to allow the removal of objects in the
   /// middle of the queue. When System.Collections.Generic.Queue searching for elements
   /// was harder due to the available methods. Elements in the list can be accessed using
   /// the [] operator, the same as elements from an array are accessed.
   /// </summary>
   [Serializable]
   public sealed class TransactieQueue : List<Transactie>
   {
      static TransactieQueue instance = null;
      static readonly object padlock = new object();
      static Thread messageSendThread;

      #region Singleton
      TransactieQueue()
      {
         messageSendThread = new Thread(SendTransactie);
      }

      public static TransactieQueue Instance
      {
         get
         {
            lock (padlock)
            {
               if (instance == null)
               {
                  instance = new TransactieQueue();
                  instance.threadStart();
               }
               return instance;
            }
         }
      }
      #endregion

      public void Enqueue(Transactie t)
      {
         this.Add(t);
      }

      public Transactie Dequeue()
      {
         Transactie t = (Transactie)this[Count];
         this.RemoveAt(this.Count);
         return t;
      }

      public void threadStart()
      {
         messageSendThread.Start();
      }

      public void SendTransactie()
      {
         while (null != instance)
         {
            if (this.Count > 0)
            {
               // Call ERP method to create the factuur on the ERP system.
               ERP.transactie transactie = new ERP.transactie();
               bool test = transactie.isGeregistreerdeKlant(this[0].Klant);

               int responseCode = this.ResponseStringToInt(transactie.createFactuurTransactie(this[0].Factuur));
               if (responseCode == (int)Global.RespondeCodes.TRANSACTION_SUCCES)
               {
                  this.Dequeue();

               }
               else if (responseCode == (int)Global.RespondeCodes.TRANSACTION_FAILED)
               {
                  Global.WriteDebugLine("Failed to create factuur transactie!");
               }
            }
            Thread.Sleep(2000); // Send one every two seconds (so the max is 30 per minute)
         }
      }

      public int ResponseStringToInt(string response)
      {
         int responseCode = 0;
         Regex r = new Regex(@"\[*\]");
         Match m = r.Match(response);
         if (m.Success)
         {
            string delim = "*[|]";
            string str = response.Substring(0, m.Index).Trim(delim.ToCharArray());
            responseCode = Int32.Parse(str);
         }
         return responseCode;
      }
   }
}
